﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using Newtonsoft.Json;

namespace SystmicFunction.Public.NetService
{
    /// <summary>
    ///     Http
    /// </summary>
    public static class HttpHelper
    {
        private const string DefaultUserAgent =
            "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)";

        /// <summary>
        ///     创建GET方式的HTTP请求
        /// </summary>
        /// <param name="host">请求的主机头：www.baidu.com/login.aspx</param>
        /// <param name="isHttps">是否为https</param>
        /// <param name="dict">请求的参数：Key:Name,Value:1</param>
        /// <param name="timeout">请求的超时时间</param>
        /// <param name="userAgent">请求的客户端浏览器信息，可以为空</param>
        /// <param name="cookies">随同HTTP请求发送的Cookie信息，如果不需要身份验证可以为空</param>
        /// <returns></returns>
        public static HttpWebResponse CreateGetHttpResponse(string host, bool isHttps, Dictionary<string, Object> dict, int? timeout,
                                                            string userAgent,
                                                            CookieCollection cookies)
        {

            string url = FormatUrl(host, isHttps, dict);

            if (string.IsNullOrEmpty(url))
            {
                throw new ArgumentNullException(url);
            }
            var request = (HttpWebRequest)WebRequest.Create(url);

            request.Method = "GET";

            request.UserAgent = DefaultUserAgent;
            if (!string.IsNullOrEmpty(userAgent))
            {
                request.UserAgent = userAgent;
            }
            if (timeout.HasValue)
            {
                request.Timeout = timeout.Value;
            }
            if (cookies != null)
            {
                request.CookieContainer = new CookieContainer();
                request.CookieContainer.Add(cookies);
            }
            return (HttpWebResponse)request.GetResponse();
        }


        /// <summary>
        ///     发送
        /// </summary>
        /// <param name="response"></param>
        /// <param name="type">返回Json可以转换的类型</param>
        /// <returns>没有值返回</returns>
        public static Object GetObject(HttpWebResponse response, Type type)
        {
            Stream responseStream = response.GetResponseStream();

            if (responseStream != null)
            {
                using (var streamReader = new StreamReader(responseStream))
                {
                    return JsonConvert.DeserializeObject(streamReader.ReadToEnd(), type);
                }
            }

            return null;
        }

        public static String GetStr(HttpWebResponse response)
        {
            Stream responseStream = response.GetResponseStream();

            if (responseStream != null)
            {
                using (var streamReader = new StreamReader(responseStream))
                {
                    return streamReader.ReadToEnd();
                }
            }

            return null;
        }

        /// <summary>
        ///     拼接GET的URL
        /// </summary>
        /// <param name="host">域名主机头</param>
        /// <param name="isHttps">是否为https</param>
        /// <param name="parmDict">参数</param>
        /// <returns>GET类型的URL</returns>
        public static string FormatUrl(string host, bool isHttps, Dictionary<string, Object> parmDict)
        {
            string url = isHttps ? "Https://{0}?{1}" : "Http://{0}?{1}";

            const string parmStr = "{0}={1}&";
            string parmUrl = parmDict.Aggregate("",
                                                (current, able) =>
                                                current + string.Format(parmStr, able.Key, able.Value));

            return string.Format(url, host, parmUrl).Replace("{0}={1}&", "");
        }

        #region Post

        /// <summary>
        ///     创建POST方式的HTTP请求
        /// </summary>
        /// <param name="url">请求的URL</param>
        /// <param name="parameters">随同请求POST的参数名称及参数值字典</param>
        /// <param name="timeout">请求的超时时间</param>
        /// <param name="userAgent">请求的客户端浏览器信息，可以为空</param>
        /// <param name="requestEncoding">发送HTTP请求时所用的编码</param>
        /// <param name="cookies">随同HTTP请求发送的Cookie信息，如果不需要身份验证可以为空</param>
        /// <returns></returns>
        public static HttpWebResponse CreatePostHttpResponse(string url, IDictionary<string, Object> parameters,
                                                             Int32? timeout, string userAgent, Encoding requestEncoding,
                                                             CookieCollection cookies)
        {
            var request = CRequest(url, timeout, userAgent, requestEncoding, cookies);
            CrBody(parameters, requestEncoding, request);
            return request.GetResponse() as HttpWebResponse;
        }

        public static HttpWebResponse CreatePostHttpResponse(string url, String bodyStr,
                                                             Int32? timeout, string userAgent, Encoding requestEncoding,
                                                             CookieCollection cookies)
        {
            var request = CRequest(url, timeout, userAgent, requestEncoding, cookies);
            CrBody(bodyStr, requestEncoding, request);
            return request.GetResponse() as HttpWebResponse;
        }

        private static HttpWebRequest CRequest(string url, Int32? timeout, string userAgent, Encoding requestEncoding, CookieCollection cookies)
        {
            if (string.IsNullOrEmpty(url))
            {
                throw new ArgumentNullException("url");
            }
            if (requestEncoding == null)
            {
                throw new ArgumentNullException("requestEncoding");
            }
            HttpWebRequest request = null;
            //如果是发送HTTPS请求  
            if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase))
            {
                ServicePointManager.ServerCertificateValidationCallback = CheckValidationResult;
                request = WebRequest.Create(url) as HttpWebRequest;
                request.ProtocolVersion = HttpVersion.Version10;
            }
            else
            {
                request = WebRequest.Create(url) as HttpWebRequest;
            }
            request.Method = "POST";
            request.ContentType = "application/x-www-form-urlencoded";

            request.UserAgent = !string.IsNullOrEmpty(userAgent) ? userAgent : DefaultUserAgent;

            if (timeout.HasValue)
            {
                request.Timeout = timeout.Value;
            }
            if (cookies != null)
            {
                request.CookieContainer = new CookieContainer();
                request.CookieContainer.Add(cookies);
            }
            return request;
        }

        private static void CrBody(String bodyStr, Encoding requestEncoding, HttpWebRequest request)
        {
            byte[] data = requestEncoding.GetBytes(bodyStr);
            using (Stream stream = request.GetRequestStream())
            {
                stream.Write(data, 0, data.Length);
            }

        }

        private static void CrBody(IDictionary<string, Object> parameters, Encoding requestEncoding, HttpWebRequest request)
        {
            if (!(parameters == null || parameters.Count == 0))
            {
                var buffer = new StringBuilder();
                int i = 0;
                foreach (string key in parameters.Keys)
                {
                    buffer.AppendFormat(i > 0 ? "&{0}={1}" : "{0}={1}", key, parameters[key]);
                    i++;
                }
                CrBody(buffer.ToString(), requestEncoding, request);
            }
        }

        private static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain,
                                                  SslPolicyErrors errors)
        {
            return true; //总是接受  
        }

        #endregion
    }
}